package com.frontend.screens;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.Calendar;

import javax.swing.*;

import com.data.documents.Appointment;
import com.frontend.ConnectionException;
import com.frontend.DoctorsOfficeClient;
import com.users.User;
import com.util.JTextFieldLimit;
import com.util.DaysCount;

/**
 * The Appointment Screen displays an appointment form to the User
 * 
 * @author Elizabeth
 * 
 */
public class AppointmentScreen extends Screen {

	/**
	 * 
	 */
	private static final long serialVersionUID = -5356432986194561318L;
	private JLabel dateLabel, timeLabel, reasonLabel, desiredDoctorLabel,
			message;
	private JTextField reason;
	private JComboBox desiredDoctor, time;
	private JComboBox day, month, year;
	private JButton submit, back;
	private String[] doctors, times;
	private boolean block;
	private javax.swing.Timer timer;
	private int cycles;
	private Appointment a;
	private User u;
	private Screen prevScreen;
	private Calendar calendar;
	/**
	 * Makes the appointment page. If a brand new appointment is being created,
	 * there is nothing in it. If it is being edited, the values from the
	 * appointment are filled into the text boxes
	 * 
	 * @param window
	 * @param a
	 */
	public AppointmentScreen(DoctorsOfficeClient window, Appointment a, User u,
			Screen prevScreen) {
		super(window);

		this.prevScreen = prevScreen;
		this.a = a;
		this.u = u;
		this.calendar = Calendar.getInstance();
		if (a.getDateTime() != 0)
			calendar.setTimeInMillis(a.getDateTime());
		times = getTimesArray();
		setLayout(null);
		timer = new javax.swing.Timer(50, new AnimationListener());
		block = true;
		AppointmentListener al = new AppointmentListener();

		message = new JLabel("Make an Appointment");
		message.setAlignmentX(CENTER_ALIGNMENT);

		DateItemListener dil = new DateItemListener();

		int currentYear = calendar.get(Calendar.YEAR);
		Integer[] years = new Integer[100];
		for (int i = 0; i < 100; i++) {
			years[i] = currentYear + i - 50;
		}
		year = new JComboBox(years);
		year.setSelectedItem(new Integer(currentYear));
		year.addItemListener(dil);

		int currentMonth = calendar.get(Calendar.MONTH);
		String[] monthList = getMonthStrings();
		month = new JComboBox(monthList);
		month.setSelectedIndex(currentMonth);
		month.addItemListener(dil);

		int numDays = DaysCount.daysIn(currentMonth, currentYear);
		Integer[] days = new Integer[numDays];
		for (int i = 0; i < numDays; i++) {
			days[i] = i + 1;
		}
		int currentDay = calendar.get(Calendar.DAY_OF_MONTH);
		day = new JComboBox(days);
		day.setSelectedIndex(currentDay - 1);

		dateLabel = new JLabel("Date: ");
		dateLabel.setHorizontalAlignment(SwingConstants.TRAILING);
		add(dateLabel);
		add(day);
		add(month);
		add(year);

		timeLabel = new JLabel("Time: ");
		timeLabel.setHorizontalAlignment(SwingConstants.TRAILING);
		time = new JComboBox(times);
		int index = (calendar.get(Calendar.HOUR_OF_DAY)) * 2;
		if (calendar.get(Calendar.MINUTE) != 0)
			index++;
		time.setSelectedIndex(index);
		add(timeLabel);
		add(time);

		reasonLabel = new JLabel("Reason for Appointment: ");
		reasonLabel.setHorizontalAlignment(SwingConstants.TRAILING);
		reason = new JTextField();
		reason.setDocument(new JTextFieldLimit(200));
		reason.addActionListener(al);
		add(reasonLabel);
		add(reason);

		try {
			doctors = window.getNet().listUsersNames(User.DOCTOR);
		} catch (ConnectionException e) {
			System.out.println(e.getMessage());
		}

		desiredDoctorLabel = new JLabel("Desired Doctor: ");
		desiredDoctorLabel.setHorizontalAlignment(SwingConstants.TRAILING);
		desiredDoctor = new JComboBox(doctors);
		desiredDoctor.setOpaque(false);
		add(desiredDoctorLabel);
		add(desiredDoctor);

		submit = new JButton("Submit");
		back = new JButton("Back");
		submit.addActionListener(al);
		back.addActionListener(al);
		submit.setOpaque(false);
		back.setOpaque(false);

		reason.setText(a.getReason());
		if (a.getDesiredDoctor() != null)
			desiredDoctor.setSelectedItem(a.getDesiredDoctor().getName());

		add(message);
		add(submit);
		add(back);
	}

	/**
	 * Makes it pretty
	 */
	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		if (getHeight() != tempheight || getWidth() != tempwidth) {
			int height = getHeight();
			int width = getWidth();
			Insets insets = getInsets();
			int curY = height / 15;

			FontMetrics fm = g.getFontMetrics(new Font("Arial", Font.BOLD,
					getHeight() / 15));
			int textWidth = (int) fm.getStringBounds(message.getText(), g)
					.getWidth();

			message.setFont(new Font("Arial", Font.BOLD, getHeight() / 15));
			message.setBounds(width / 2 + insets.left - textWidth / 2, curY,
					width, height / 15);
			curY += height / 15;
			curY += height / 10;

			dateLabel.setFont(new Font("Arial", Font.PLAIN, getHeight() / 20));
			dateLabel.setBounds(width / 2 - width / 60 - 2 * width / 5 - width
					/ 30 + insets.left, curY, width / 5, height / 15);
			day.setFont(new Font("Arial", Font.PLAIN, getHeight() / 20));
			day.setBounds(width / 2 + width / 60 + insets.left, curY,
					width / 5, height / 15);
			month.setFont(new Font("Arial", Font.PLAIN, getHeight() / 20));
			month.setBounds(width / 2 - width / 60 - width / 5 + insets.left,
					curY, width / 5, height / 15);
			year.setFont(new Font("Arial", Font.PLAIN, getHeight() / 20));
			year.setBounds(width / 2 + width / 60 + width / 5 + insets.left
					+ width / 30, curY, width / 5, height / 15);

			curY += height / 15;
			curY += height / 10;

			timeLabel.setFont(new Font("Arial", Font.PLAIN, getHeight() / 20));
			timeLabel.setBounds(width / 2 + insets.left - width / 60 - width
					/ 4, curY, width / 4, height / 15);
			time.setFont(new Font("Arial", Font.PLAIN, getHeight() / 20));
			time.setBounds(width / 2 + insets.left + width / 60, curY,
					width / 4, height / 15);

			curY += height / 15;
			curY += height / 10;

			reasonLabel
					.setFont(new Font("Arial", Font.PLAIN, getHeight() / 20));
			reasonLabel.setBounds(width / 2 - width * 3 / 7 + insets.left,
					curY, width * 3 / 7, height / 15);
			reason.setFont(new Font("Arial", Font.PLAIN, getHeight() / 20));
			reason.setBounds(width / 2 + insets.left, curY, 3 * width / 7,
					height / 15);

			curY += height / 15;
			curY += height / 10;

			desiredDoctorLabel.setFont(new Font("Arial", Font.PLAIN,
					getHeight() / 20));
			desiredDoctorLabel.setBounds(width / 2 - width * 3 / 7
					+ insets.left, curY, width * 3 / 7, height / 15);
			desiredDoctor.setFont(new Font("Arial", Font.PLAIN,
					getHeight() / 20));
			desiredDoctor.setBounds(width / 2 + insets.left, curY,
					3 * width / 7, height / 15);

			curY += height / 15;
			curY += height / 10;

			submit.setMaximumSize(new Dimension(getWidth() / 5,
					getHeight() / 15));
			submit.setFont(new Font("Arial", Font.PLAIN, getHeight() / 20));
			submit.setBounds(width / 2 + insets.left - width / 5 - width / 60,
					curY, width / 5, height / 15);
			back.setMaximumSize(new Dimension(getWidth() / 5, getHeight() / 15));
			back.setFont(new Font("Arial", Font.PLAIN, getHeight() / 20));
			back.setBounds(width / 2 + insets.left + width / 60, curY,
					width / 5, height / 15);

			tempheight = getHeight();
			tempwidth = getWidth();
		}
	}

	/**
	 * The listener for all the buttons and fields in the appointment screen
	 * @author Elizabeth
	 *
	 */
	private class AppointmentListener implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			if (e.getSource() == back) {
				window.changeScreen(prevScreen);
				prevScreen.repaint();
				if (prevScreen instanceof PatientOverviewScreen) {
					((PatientOverviewScreen) prevScreen).search();
				}

			} else {
				a.setReason(reason.getText());
				try {
					a.setDesiredDoctor(window.getNet().getUser(
							(String) desiredDoctor.getSelectedItem(),
							User.DOCTOR));
				} catch (ConnectionException e2) {
					System.out.println(e2.getMessage());
				}
				block = false;

				if (a.getReason().equals("")) {
					block = true;
					showError("Reason field cannot be blank");
				}

				if (!block) {
					int yr = (Integer) year.getSelectedItem();
					int mnth = month.getSelectedIndex();
					int d = day.getSelectedIndex() + 1;
					String t = (String) time.getSelectedItem();
					int hr = Integer.parseInt(t.split(":")[0]);
					int min = Integer.parseInt(t.split(":")[1]);
					calendar.set(yr, mnth, d, hr, min);
					a.setDateTime(calendar.getTimeInMillis());
					try {
						window.getNet().updateDocument(a, u.getUsername());
						block = true;
						showError("Appointment Submitted!");
					} catch (ConnectionException e2) {
						e2.printStackTrace();
					}
				}
			}
		}
	}

	/**
	 * Show the message in red when something goes wrong
	 * @param line
	 */
	private void showError(String line) {
		timer.stop();
		block = true;
		cycles = 0;
		message.setText(line);
		message.setForeground(Color.red);
		timer.start();
	}

	private class DateItemListener implements ItemListener {

		@Override
		public void itemStateChanged(ItemEvent arg0) {
			int currentMonth = month.getSelectedIndex();
			int currentYear = (Integer) year.getSelectedItem();
			int currentDay = (Integer) day.getSelectedItem();
			int numDays = DaysCount.daysIn(currentMonth, currentYear);
			if (currentDay > numDays)
				currentDay = numDays;
			day.removeAllItems();
			for (int i = 0; i < numDays; i++) {
				day.insertItemAt((Integer) (i + 1), i);
			}
			day.setSelectedIndex(currentDay - 1);
			revalidate();
			repaint();
		}

	}

	private class AnimationListener implements ActionListener {
		private int alphaVal;
		private boolean fadeout, fadein;

		@Override
		public void actionPerformed(ActionEvent e) {
			if (cycles == 0) {
				alphaVal = 255;
				fadeout = true;
				fadein = false;
			}
			cycles++;

			if (cycles > 20) {
				if (fadeout) {
					alphaVal = alphaVal - 10;
					if (alphaVal < 0)
						alphaVal = 0;
					Color tc = message.getForeground();
					message.setForeground(new Color(tc.getRed(), tc.getBlue(),
							tc.getGreen(), alphaVal));
					repaint();
					if (alphaVal == 0) {
						fadeout = false;
						fadein = true;
						message.setText("Make an Appointment");
					}
				}
				if (fadein) {
					alphaVal += 10;
					if (alphaVal > 255)
						alphaVal = 255;
					message.setForeground(new Color(0, 0, 0, alphaVal));
					repaint();
					if (alphaVal == 255) {
						fadein = false;
						timer.stop();
					}
				}
			}
		}

	}

}
